/*Aufgabe 2*/
import de.medieninf.ads.ADSTool;

/**Mainklasse und Programm zum manipulieren
 * von Graustufenbildern im pgm-Format.
 * Ausser der Mainmethode gibt es 4 weitere
 * Methoden .
 * 
 * Methoden:  max, min, getSmallesPixel, getLargestPixel, heller
 * 			  getArray und kanten
 * 
 * @authoren Anna Maciejewska, Gerd Ohlweiler, Bjoern Klemm
 *
 */



public class Aufgabe2 {

	
	/**
	 * Returns the max-Value of two integer-values
	 * @param x the first integer-value
	 * @param y the second integer-value
	 */
	public static int max(int x, int y) {	
		if(x > y)
			return x;
		else
			return y;

	}
	/**
	 * Returns the min-Value of two integer-values
	 * @param x the first integer-value
	 * @param y the second integer-value
	 * @return
	 */
	public static int min(int x,int y) {
		if(x > y)
			return y;
		else
			return x;
	}
		

	/**
	 * Converts a two-dimensional array to a one-dimensional pgm-file array
	 * @param sourceField
	 * @param sourceImage
	 * @return
	 */
	public static int[]getArray(int[][]targetField,int[]sourceImage) {

		//Create a new array with the length of the original image-file
		int [] returnField = new int [(sourceImage[0]*sourceImage[1])+3];
		int p = 0;

		//Copy every image-value to the new image-file
			for(int i = 0;i<sourceImage[0];i++) {	
				for(int j = 0;j<sourceImage[1];j++) {
					returnField[p] = targetField[i][j];
					p++;
				}
			}

		return returnField;
		
	}
	
	
	/**
	 * Converts a two-dimensional array of a one-dimensional array, containing a
	 * pgm-file
	 * 
	 * @param sourceImage
	 * @return
	 */

	public static int[][] getField(int[] sourceImage) {

		// Create a new to-dimensional field with the size of the source image
		int[][] returnField = new int[sourceImage[0]][sourceImage[1]];

		// Set the counter to 3, to ignore the default values at the beginning
		// of the image-array (height, etc.)
		int sourceCounter = 3;

		// Write the image-file values to the two-dimensional array
		for (int i = 0; i < sourceImage[0]; i++) {
			for (int j = 0; j < sourceImage[1]; j++) {

				returnField[i][j] = sourceImage[sourceCounter];
				sourceCounter++;
			}
		}

		return returnField;

	}
	
	/**
	 * Returns the smallest Value inside a specific field range
	 * 
	 * @param xMin
	 * @param xMax
	 * @param yMin
	 * @param yMax
	 * @param x
	 * @param y
	 * @param sourceField
	 * @return
	 */
	public static int getSmallestValue(int xMin, int xMax, int yMin, int yMax, int x, int y, int[][]sourceField) {	
		//Set the smallest Value to the center-point of the field range
		
		int smallestValue = sourceField[x][y];
		
		//Check if there is a smaller value in a field around the center-point
	
		
		for (int i = xMax;i<=xMin;i++) {		
			for(int j = yMax;j<=yMin;j++) {
				if(sourceField[i][j] < smallestValue) {
					smallestValue = sourceField[i][j];			
				}
			}
		}

		return smallestValue;
	
	}	
	
	/**
	 * Converts a pgm-file to a brighter version
	 * @param sourceImage
	 * @param p
	 * @return
	 */
	public static int[] minimum(int[]sourceImage,int p) {

		//Create a new two-dimensional field and put the original pgm image into it
		//int sourceField[][] = ADSTool.feld2FeldFeld(sourceImage);

		int sourceField[][] = getField(sourceImage);

		//Create a new two-dimensional field with the size of the original pgm image, to put
		//the new image into it
		int targetField[][] = new int[sourceImage[0]][sourceImage[1]];

		
		//Calculate the new brightnes around the given range (p)
		for(int x = 0;x<=sourceImage[0]-(int)(p/2);x++) {
			for(int y = 0;y<=sourceImage[1]-(int)(p/2);y++) {	
				int xMin = min((sourceImage[0])-1,x+(int)(p/2));
				int xMax = max(0,x-(int)(p/2));
				int yMin = min((sourceImage[1])-1,y+(int)(p/2));
				int yMax = max(0,y-(int)(p/2));

				//Write the smallest value to the target image-file 
				//System.out.println("getSV- xMin:"+xMin+" xMax: "+xMax+" yMin: "+yMin+" yMax: "+yMax+" x: "+x+" y: "+y);
				targetField[x][y] = getSmallestValue(xMin, xMax, yMin, yMax, x,y,sourceField);	
				
			}
			
		}
		int[] result = getArray(targetField,sourceImage);
		result[0] = sourceImage[0];
		result[1] = sourceImage[1];
		result[2] = sourceImage[2];

		return result;	
	}
	
	public static int[] kanten(int[] pgmIn, int p){
		
		if(p != 3)
			System.out.println("Parameter muss 3 sein!");
		else{
			
			int[] pgmOut = new int[pgmIn.length];
			int min = pgmOut[2] = pgmIn[2];
			int width = pgmOut[1] = pgmIn[1];
			int height = pgmOut[0] = pgmIn[0];
			int cmp = 0, index = 0;
			
			for(int i = 1; i < height-1;i++ ){
				for(int j = 1; j < width-1;j++){
					min = 255;
					//Umgebung berechnen
					for(int k = -1; k <= 1; k++){
						for(int v = -1; v <= 1; v++){
							cmp = pgmIn[(i+k)*width+(j+v)];
							if(min > cmp)
								min = cmp;
						
						}
					}
					index = i*width+j;
					pgmOut[index] = pgmIn[index]-min;
				}
			}
			return pgmOut;
		}
		return null;
	}
	/**
	 * Methode zum Anzeigen: Wie benutze ich das Programm?
	 * Nach der Hilfeanzeige wird das Programm beendet.
	 */
	public static void errorMsg(){
		System.out.println("----------------------------------------------------------------------------------------------------------------------------------");
		System.out.println("|                                                                                                                         	     |");
		System.out.println("|	Sie muessen 4 Parameter angeben! methode(Param1) wert(Param2) einlesebild.pgm(Param3) ausgabebild.pgm(Param4)          		 |");
		System.out.println("|	Bsp. java -jar aufg1.jar gamma 1.4 a.pgm out.pgm                                                                             |");
		System.out.println("|	Bitte Kleinschreibung und korrekte Reihenfolge beachten!                                                                     |");
		System.out.println("|	Bei dem Bilddateiformat muss es sich um das PGM-Format handeln!                                                              |");
		System.out.println("|                                                                                                                            	 |");
		System.out.println("----------------------------------------------------------------------------------------------------------------------------------");
		System.exit(-1);
	}
	
	public static void main(String[] args) {
		
		if (args.length != 4) 
			errorMsg();
		else {

			String function = args[0];
			String value = args[1];
			String sourceFile = args[2];
			String targetFile = args[3];

			
			
			int[] sourceImage = ADSTool.readPGM(sourceFile);
			int p = Integer.valueOf(value);
			
			if (function.equals("minimum")) {
				if(p%2 == 0 && p<3) 
					System.out.println("Parameter nicht ungerade! ");
				else {
					int [] targetImage = minimum(sourceImage,p);
					
					ADSTool.savePGM(targetFile, targetImage);
				}
				
			} else if(function.equals("kanten")) {
				sourceImage = kanten(sourceImage,p);	
				ADSTool.savePGM(targetFile, sourceImage);
			}			
		}
	}
}
